package com.bitoon.basketdudes.web.admin;

import com.bitoon.basketdudes.web.BaseAction;
import com.bitoon.basketdudes.web.datos.InfoCabeceraXHR;
import com.bitoon.basketdudes.web.jpa.AdmRol;
import com.bitoon.basketdudes.web.jpa.AdmRolSeccion;
import com.bitoon.basketdudes.web.jpa.AdmRolSeccionPK;
import com.bitoon.basketdudes.web.jpa.AdmSeccion;
import java.util.regex.*;

import java.util.*;
import javax.persistence.*;
import org.apache.log4j.Logger;

public class ListaRolesAdmin extends BaseAction {
    
    private List<AdmRol> datos;
    private InfoCabeceraXHR cabecera;
    private int pagina = 1;
    private int cuantos;
    
    private static String patternNick = "[0-9a-zA-Z._@#-]+";

    private boolean insertar;
    private boolean error;
    private boolean modificar;
    private int rol;
    private AdmRol dato;
    private String[] lectura;
    private String[] escritura;
    private String nombre;
    private String descripcion;
    private String accion;
    private String[] id_rol;

    private List<AdmRol> listaRoles;
    private List<String> listaNombreSecciones;

    private Logger log = Logger.getLogger(ListaRolesAdmin.class);

    //acceso a la clase estatica BaseActionAdmin
    protected BaseActionAdmin bsaadmin = BaseActionAdmin.getInstance();

    @Override
    public String execute() {

        try {
            // El método sólo se ejecuta al principio, la paginación va por consultaXhr
            listaRoles(BaseActionAdmin.LISTADO_ROLES_ELEMENTOS_POR_PAGINA,BaseActionAdmin.LISTADO_ROLES_HUECOS_LADO_PAGINA);

        } catch (Exception e) {
            log.error("Error", e);
        }

        return SUCCESS;
    }

    public String consultaXhr() {

        listaRoles(cuantos, BaseActionAdmin.LISTADO_ADMINISTRADORES_HUECOS_LADO_PAGINA);

        return SUCCESS;
    }

    private void listaRoles(int elementos, int huecos) {
        List<AdmRol> retorno = null;
        EntityManager em = null;

        try {
            log.debug("Listando los roles de los usuarios admin");
            retorno = new ArrayList<AdmRol>();

            em = bsaadmin.getEmfAdmin().createEntityManager(); // checked
            
            Query q = em.createNamedQuery("AdmRol.findAllOrderByNombre");
            
            int totalRegistros = q.getResultList().size();
            //log.debug("totalRegistros: " + totalRegistros);
            int totalPaginas = (totalRegistros-1)/elementos + 1;

            int offset = (pagina-1) * elementos;
            int first = (pagina-1)*elementos; //primer registro
            int max = elementos; //ultimo registro
            
            q = em.createNamedQuery("AdmRol.findAllOrderByNombre");
            q.setFirstResult(first);
            q.setFirstResult(offset);
            q.setMaxResults(max);

            retorno = (List<AdmRol>)q.getResultList();

            log.debug("retorno: " + retorno.size());

            cabecera = new InfoCabeceraXHR();
            cabecera.setCorrecto(1);
            cabecera.setActual(pagina);
            cabecera.setTotal(totalPaginas);

            int p1=0, p2=0;

            if (pagina <= (huecos+1)) {
                p1 = 1;
                p2 = huecos*2 + 1;
            } else if (pagina >= (totalPaginas-huecos)) {
                p1 = totalPaginas - (huecos*2);
                p2 = totalPaginas;
            } else {
                p1 = pagina - huecos;
                p2 = pagina + huecos;
            }
            if (p1 < 1) {
                p1 = 1;
            }
            if (p2 > totalPaginas) {
                p2 = totalPaginas;
            }
            cabecera.setPrimeraPagina(p1);
            cabecera.setUltimaPagina(p2);

            setDatos(retorno);
            setCabecera(cabecera);

        } catch (Exception e) {
            log.error("[buscaRoles] Error: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }
    }

    private boolean datosValidos(String nombre){
        boolean retorno = true; //por defecto es válido

        //que el nick tenga unos caracteres en croncreto
        if(nombre.length()==0 || Pattern.matches(patternNick,nombre)==false){
            log.debug("[Validacion] nombre incorrecto");
            retorno = false;
        }
        
        return retorno;
    }

    public String consultaRolAdmin() {
        EntityManager em = null;
        String retorno = SUCCESS;
        AdmRol rol_bd = null;

        if(isModificar()){
            //si hay que modificar la informacion
            retorno = modificarRol();
        }else{
            //si hay que consultar la información
            try {
                log.debug("Consulto: " + isModificar()+ "-" + getRol());
                em = bsaadmin.getEmfAdmin().createEntityManager(); // checked

                Query q  = em.createNamedQuery("AdmRol.findById");
                q.setParameter("id", rol);

                rol_bd = (AdmRol)q.getSingleResult();

                setDato(rol_bd);

            } catch (NoResultException e) {
                log.debug("[consultaRolAdmin]rol " + rol + " no encontrado");
            } catch (Exception e) {
                log.error("[consultaRolAdmin]: ", e);
            } finally {
                try { em.close(); } catch (Exception e) { }
            }
        }

        return retorno;
    }

    private String modificarRol(){
        EntityManager em = null;
        String retorno = "mod_ok";
        AdmRol adrol = null;

        //log.debug("Modifico: " + isModificar()+ "-" + rol);
        if(datosValidos(getNombre())){
            try {
                em = bsaadmin.getEmfAdmin().createEntityManager(); // checked

                Query q  = em.createNamedQuery("AdmRol.findById");
                q.setParameter("id", rol);

                adrol = (AdmRol)q.getSingleResult();

                if(adrol!=null){
                    //rol encontrado
                    em.getTransaction().begin();

                    //log.debug("[Modifico] nombre: "+nombre+" desc:" + descripcion +" lectura:" +getLectura() + " escritura: " + escritura);
                    AdmRolSeccion ars = null;
                    ArrayList<Integer> ids = null;
                    if(getLectura()!=null){
                        
                        //almaceno las secciones pasadas como parámetros
                        ids = new ArrayList<Integer>();
                        for(String l:getLectura()){
                            
                            String[] partes = l.split("-");
                            ids.add(Integer.parseInt(partes[1]));
                            q  = em.createNamedQuery("AdmRolSeccion.findByRolSeccionIds");
                            q.setParameter("admRoleId", Integer.parseInt(partes[0]));
                            q.setParameter("ademSectionId", Integer.parseInt(partes[1]));
                            ars = (AdmRolSeccion)q.getSingleResult();

                            if(ars.getPermiso()==0){
                                ars.setPermiso((short)1);
                            }else{
                                if(ars.getPermiso()==2){
                                    ars.setPermiso((short)(ars.getPermiso()+1));
                                }
                            }
                            em.persist(ars);
                        }
                        //pongo a cero todos los demas
                        boolean sw=true;
                        for(int i=0;i<adrol.getAdmRolSeccionList().size();++i){
                            for(int j=0;j<ids.size();++j){
                                if(adrol.getAdmRolSeccionList().get(i).getAdmSeccion().getId().intValue()==ids.get(j).intValue()){
                                    //si se encuentra en la lista,no hay que quitarle los permisos
                                    sw=false;
                                }
                            }
                            if(sw==true){
                                if(adrol.getAdmRolSeccionList().get(i).getPermiso()==1 || adrol.getAdmRolSeccionList().get(i).getPermiso()==3){
                                    adrol.getAdmRolSeccionList().get(i).setPermiso((short)(ars.getPermiso()-1));
                                }
                            }
                            sw=true; //por defecto no a sido pasado por parametro la seccion
                        }
                    }else{
                        for(int i=0;i<adrol.getAdmRolSeccionList().size();++i){
                            if(adrol.getAdmRolSeccionList().get(i).getPermiso()>0){
                                if(adrol.getAdmRolSeccionList().get(i).getPermiso()==1 || adrol.getAdmRolSeccionList().get(i).getPermiso()==3){
                                   adrol.getAdmRolSeccionList().get(i).setPermiso((short)(adrol.getAdmRolSeccionList().get(i).getPermiso()-1));
                                }
                            }
                        }
                    }
                    
                    if(escritura!=null){
                        //almaceno las secciones pasadas como parámetros
                        ids = new ArrayList<Integer>();
                        for(String e:escritura){
                            
                            String[] partes = e.split("-");
                            ids.add(Integer.parseInt(partes[1]));
                            q  = em.createNamedQuery("AdmRolSeccion.findByRolSeccionIds");
                            q.setParameter("admRoleId", Integer.parseInt(partes[0]));
                            q.setParameter("ademSectionId", Integer.parseInt(partes[1]));
                            ars = (AdmRolSeccion)q.getSingleResult();

                            if(ars.getPermiso()==0){
                                ars.setPermiso((short)2);
                            }else{
                                if(ars.getPermiso()==1){
                                    ars.setPermiso((short)(ars.getPermiso()+2));
                                }
                            }
                            em.persist(ars);
                        }
                        boolean sw=true; //por defecto no a sido pasado por parametro la seccion
                        //pongo a cero todos los demas
                        for(int i=0;i<adrol.getAdmRolSeccionList().size();++i){
                            for(int j=0;j<ids.size();++j){
                                if(adrol.getAdmRolSeccionList().get(i).getAdmSeccion().getId().intValue()==ids.get(j).intValue()){
                                    //si se encuentra en la lista,no hay que quitarle los permisos
                                    sw=false;
                                }
                            }
                            if(sw==true){
                                if(adrol.getAdmRolSeccionList().get(i).getPermiso()>=2){
                                    adrol.getAdmRolSeccionList().get(i).setPermiso((short)(adrol.getAdmRolSeccionList().get(i).getPermiso()-2));
                                }
                            }
                            sw=true;
                        }
                    }else{
                        for(int i=0;i<adrol.getAdmRolSeccionList().size();++i){
                            if(adrol.getAdmRolSeccionList().get(i).getPermiso()>0){
                                if(adrol.getAdmRolSeccionList().get(i).getPermiso()>=2){
                                    adrol.getAdmRolSeccionList().get(i).setPermiso((short)(adrol.getAdmRolSeccionList().get(i).getPermiso()-2));
                                }
                            }
                        }
                    }

                    if(lectura==null && escritura==null){
                        for(int i=0;i<adrol.getAdmRolSeccionList().size();++i){
                            adrol.getAdmRolSeccionList().get(i).setPermiso((short)0);
                        }
                    }

                    //modifico los datos del rol
                    adrol.setNombre(nombre);
                    adrol.setDescripcion(descripcion);
                    em.persist(adrol);

                    em.getTransaction().commit();

                    setDato(adrol);
                }

            } catch (NoResultException e) {
                log.debug("[modificarRol]rol " + rol + " no encontrado]");
                retorno = NOT_FOUND;
                setError(true);
            } catch (Exception e) {
                log.error("[modificarRol]: ", e);
                retorno = ERROR;
            } finally {
                try { em.close(); } catch (Exception e) { }
            }
        }else{
            retorno =ERROR;
            setError(true);
        }

        return retorno;
    }

    public String elegirAccionRolesAdmin(){
        String retorno = "borrar";

        log.debug("Accion: " + getAccion() + " retorno: "+ retorno);

        if(getAccion().compareTo(retorno)!=0){

            retorno = "nueva";
        }

        return retorno;
    }

    public String insertarRolAdmin(){
        EntityManager em = null;
        String retorno = SUCCESS;
        AdmRol rol_bd = null;
        AdmRolSeccion rol_seccion = null;
        AdmSeccion seccion = null;

        cargarSecciones();
        if(isInsertar()){
            if(datosValidos(getNombre())){
                //si hay que insertar
                try {
                    log.debug("Inserto: " + isInsertar() + " nombre: "+nombre);

                    if(nombre!=null && nombre.compareTo("")!=0
                      && descripcion!=null && descripcion.compareTo("")!=0){
                        em = bsaadmin.getEmfAdmin().createEntityManager(); // checked

                        em.getTransaction().begin();

                        rol_bd = new AdmRol();
                        rol_bd.setId(dameUltimoIdRol()+1);
                        rol_bd.setNombre(nombre);
                        rol_bd.setDescripcion(descripcion);

                        ArrayList<AdmRolSeccion> lista = new ArrayList<AdmRolSeccion>();
                        //creamos la lista de secciones/permisos - por defecto todos a 0
                        for(int i=0;i<listaNombreSecciones.size();++i){

                            rol_seccion = new AdmRolSeccion();
                            rol_seccion.setAdmRol(rol_bd);
                            rol_seccion.setPermiso((short)0);

                            //busco el id de la seccion
                            Query q = em.createNamedQuery("AdmSeccion.findByNombre");
                            q.setParameter("nombre", (String)listaNombreSecciones.get(i));
                            seccion = (AdmSeccion)q.getSingleResult();

                            rol_seccion.setAdmSeccion(seccion);
                            rol_seccion.setAdmRolSeccionPK(new AdmRolSeccionPK(rol_bd.getId(), seccion.getId()));

                            lista.add(rol_seccion);
                        }

                        rol_bd.setAdmRolSeccionList(lista);

                        em.persist(rol_bd);

                        em.getTransaction().commit();
                    }else{
                        log.debug("[insertarRolAdmin] formulario vacio");
                        error=true;
                        retorno = "error";
                    }

                } catch (NoResultException e) {
                    log.debug("[insertarRolAdmin]rol " + rol + " no encontrado");
                    error=true;
                } catch (Exception e) {
                    log.error("[insertarRolAdmin]: ", e);
                    error=true;
                } finally {
                    try { em.close(); } catch (Exception e) { }
                }
            }else{
                error=true;
            }
        }

        return retorno;
    }

    private void cargarSecciones(){
        EntityManager em = null;
        try{
            log.debug("[cargarSecciones] cargo lista secciones");
            em = bsaadmin.getEmfAdmin().createEntityManager(); // checked
            Query q  = em.createNativeQuery("select nombre from central.adm_seccion a order by id");
            listaNombreSecciones = (ArrayList<String>)q.getResultList();

        } catch (Exception e) {
            log.error("[cargarSecciones]: ", e);
        } finally {
            try { em.close(); } catch (Exception e) { }
        }
    }

    private int dameUltimoIdRol(){
        EntityManager em = null;
        int retorno = 0;
        try{
            log.debug("[dameUltimoIdRol] cargo ultimo id");
            em = bsaadmin.getEmfAdmin().createEntityManager(); // checked
            Query q  = em.createNativeQuery("select max(id) from central.adm_rol");
            retorno = (Integer)q.getSingleResult();
            log.debug("[dameUltimoIdRol] id: "+retorno);

        } catch (Exception e) {
            log.error("[dameUltimoIdRol]: ", e);
            retorno = -1;
        } finally {
            try { em.close(); } catch (Exception e) { }
        }
        return retorno;
    }

    public String borrarRolAdmin(){

        EntityManager em = null;
        String retorno=SUCCESS;
        Query q = null;
        
        log.debug("[borrarRolAdmin] entro: " + getId_rol());

        if(getId_rol()!=null && getId_rol().length>0){
            try{
                
                em = bsaadmin.getEmfAdmin().createEntityManager(); // checked
                
                AdmRol rol_remove = null;

                for (String o : getId_rol()) {
                    log.debug("Borrar el objeto rol: " + o);

                    //busco el gashaballitem
                    q = em.createNamedQuery("AdmRol.findById");
                    q.setParameter("id", Integer.parseInt(o));
                    rol_remove = (AdmRol)q.getSingleResult();

                    if(rol_remove!=null){
                        em.getTransaction().begin();
                        em.remove(rol_remove);
                        em.getTransaction().commit();
                    }
                }

            } catch (Exception e) {
                log.error("[borrarRolAdmin]: ", e);
            } finally {
                try { em.close(); } catch (Exception e) { }
            }
        }
        
        return retorno;
    }

    public List<AdmRol> getDatos() {
        return datos;
    }

    public void setDatos(List<AdmRol> resultado) {
        this.datos = resultado;
    }

    public int getPagina() {
        return pagina;
    }

    public void setPagina(int pagina) {
        this.pagina = pagina;
    }

    public int getCuantos() {
        return cuantos;
    }

    public void setCuantos(int cuantos) {
        this.cuantos = cuantos;
    }

    public InfoCabeceraXHR getCabecera() {
        return cabecera;
    }

    public void setCabecera(InfoCabeceraXHR cabecera) {
        this.cabecera = cabecera;
    }

    public boolean isInsertar() {
        return insertar;
    }

    public void setInsertar(boolean insertar) {
        this.insertar = insertar;
    }

    public boolean isError() {
        return error;
    }

    public void setError(boolean error) {
        this.error = error;
    }

    public boolean isModificar() {
        return modificar;
    }

    public void setModificar(boolean modificar) {
        this.modificar = modificar;
    }

    public List<AdmRol> getListaRoles() {
        return listaRoles;
    }

    public void setListaRoles(List<AdmRol> listaRoles) {
        this.listaRoles = listaRoles;
    }

    public int getRol() {
        return rol;
    }

    public void setRol(int rol) {
        this.rol = rol;
    }

    public AdmRol getDato() {
        return dato;
    }

    public void setDato(AdmRol dato) {
        this.dato = dato;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getDescripcion() {
        return descripcion;
    }

    public void setDescripcion(String descripcion) {
        this.descripcion = descripcion;
    }

    public String[] getEscritura() {
        return escritura;
    }

    public void setEscritura(String[] escritura) {
        this.escritura = escritura;
    }

    public String[] getLectura() {
        return lectura;
    }

    public void setLectura(String[] lectura) {
        this.lectura = lectura;
    }

    public String getAccion() {
        return accion;
    }

    public void setAccion(String accion) {
        this.accion = accion;
    }

    public List<String> getListaNombreSecciones() {
        return listaNombreSecciones;
    }

    public void setListaNombreSecciones(List<String> listaNombreSecciones) {
        this.listaNombreSecciones = listaNombreSecciones;
    }

    public String[] getId_rol() {
        return id_rol;
    }

    public void setId_rol(String[] id_rol) {
        this.id_rol = id_rol;
    }

    public BaseActionAdmin getBsaadmin() {
        return bsaadmin;
    }

    public void setBsaadmin(BaseActionAdmin bsaadmin) {
        this.bsaadmin = bsaadmin;
    }

}